﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DiscoveryLogic.Analytics.BusinessLogic;
using DiscoveryLogic.Analytics.BusinessLogic.Dedups;
using DiscoveryLogic.Analytics.BusinessLogic.Entities;
using DiscoveryLogic.Analytics.BusinessLogic.Measures;
using DiscoveryLogic.Analytics.BusinessLogic.Rules;
using DiscoveryLogic.Analytics.DataObjects;
using DiscoveryLogic.Analytics.DataObjects.Dedup;
using DiscoveryLogic.Analytics.DataObjects.Filters;
using DiscoveryLogic.Analytics.DataObjects.Measures;
using DiscoveryLogic.Analytics.DataObjects.Networks;
using DiscoveryLogic.Analytics.DataObjects.Rules;
using DiscoveryLogic.Analytics.DataObjects.Visuals;
using DiscoveryLogic.Analytics.Diagrams.Physics;
using DiscoveryLogic.Analytics.Modules;
using DiscoveryLogic.Analytics.Modules.Clusters;
using DiscoveryLogic.Analytics.Modules.DedupRules;
using DiscoveryLogic.Analytics.Modules.Explorers;
using DiscoveryLogic.Analytics.Modules.Filters;
using DiscoveryLogic.Analytics.Modules.LinkRules;
using DiscoveryLogic.Analytics.Modules.Nodes;
using DiscoveryLogic.Analytics.Modules.VisualSettings;
using DiscoveryLogic.Analytics.UI.Common.Events;
using DiscoveryLogic.Analytics.UI.Common.Wizard;
using DiscoveryLogic.Common.Utilities;
using EntityBase=DiscoveryLogic.Analytics.DataObjects.EntityBase;

namespace DiscoveryLogic.Analytics.Diagrams.NetworkGraphs
{
	/// <summary>
	/// Interaction logic for NetworkGraphView.xaml
	/// </summary>
	public partial class NetworkGraphView : UserControl, IDisposable
    {
        #region events
	    public delegate void OnEntitySelected(EntityBase entity);
	    public event OnEntitySelected EntitySelected;

	    public delegate void OnStatusChanged(string msg, int pct);
	    public event OnStatusChanged StatusChanged;
        #endregion

        #region fields
	    private NetworkGraphPresenter _Presenter;
        #endregion

        #region ctor
        public NetworkGraphView()
		{
			InitializeComponent();
		}

        public NetworkGraphView(NetworkGraphPresenter presneter)
			: this()
		{
			_Presenter = presneter;
			_Presenter.View = this;
        }
        #endregion 

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            // this.OnViewNetwork();
            // this.UpdateScrollSize();
        }

        public void OnViewNetwork(Network network)
	    {
	        network = Network.Read(network.NetworkName);
            this.UpdateNetworkDistanceRange(network);
            NetworkVisual visual = NetworkVisual.Read(network.NetworkName);
            NetworkExclusionSetting exSetting = NetworkExclusionSetting.Read(network.NetworkName);
            NetworkInclusionSetting inSetting = NetworkInclusionSetting.Read(network.NetworkName);
            this.networkGraph.InitGraph(network,visual,inSetting,exSetting);
            this.networkGraph.StartSimulation();
	    }

        public void SubscribeViewGraphEventHandler(Network network)
        {
            this._Presenter.RegisterViewGraphEventHandler(network);
        }

	    private void networkGraph_VerticeSelected(Vertice v)
	    {
	        if(v !=null && v.Tag !=null && this.EntitySelected !=null)
	        {
	            this.EntitySelected(v.Tag);
	        }
        }

        //#region zoom
        //private void ZoomSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        //{
        //    this.Zoom = e.NewValue;
        //}

        //public double Zoom
        //{
        //    get { return ZoomSlider.Value; }
        //    set
        //    {
        //        if (value >= ZoomSlider.Minimum && value <= ZoomSlider.Maximum)
        //        {
        //            networkGraph.Scale = value;
        //            ZoomSlider.Value = value;
        //            UpdateScrollSize();
        //        }
        //    }
        //}

        //private void UpdateScrollSize()
        //{
        //    // Nothing to do if the diagram is empty.
        //    if (this.ActualWidth == 0 || this.ActualHeight == 0)
        //        return;

        //    Size diagramSize = new Size(
        //        networkGraph.ActualWidth * this.Zoom,
        //        networkGraph.ActualHeight * this.Zoom);

        //    // The grid contains the diagram, set the size of the grid so it's
        //    // large enough to allow the diagram to scroll from edge to edge.
        //    graphBorder.Width = Math.Max(0, (this.ActualWidth * 2) + diagramSize.Width - Const.PanMargin);
        //    graphBorder.Height = Math.Max(0, (this.ActualHeight * 2) + diagramSize.Height - Const.PanMargin);
        //}
        //#endregion 

        #region distance 
        private void UpdateNetworkDistanceRange(Network network)
        {
            double max = 0;
            if(network.Links !=null && network.Links.Count>0)
            {
                foreach(Link link in network.Links)
                {
                    if(link.Distance > max)
                        max = link.Distance;
                }
            }
            max = Math.Max(0, Math.Min(100, max));
            if (max > 0)
            {
                this.DistanceSlider.Maximum = max;
                this.DistanceSlider.Minimum = 0;
                this.DistanceSlider.Value = max;
                this.DistanceSlider.SmallChange = max/10;
            }
        }

        private void DistanceSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (this.networkGraph != null && !string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                if (e.NewValue >= 0 && e.NewValue <= 100)
                {
                    if (this.lblEdgeFilterType.Content.ToString() == "Hop" &&
                        this.networkGraph.SelectedVertices != null &&
                        this.networkGraph.SelectedVertices.Count == 1)
                    {
                        this.networkGraph.Graph.Filter(
                            this.networkGraph.SelectedVertices[0].Tag,
                            (int) e.NewValue);
                        this.networkGraph.StartSimulation();
                    }
                    else
                    {
                        this.networkGraph.Graph.Filter(e.NewValue);
                        this.networkGraph.StartSimulation();
                    }
                }
            }
        }
        #endregion

        #region select 
        public void SelectEntity(EntityBase entity)
        {
            this.networkGraph.SelectEntity(entity);
        }

        public void SubscribeEventHandler(EntityBase entity)
        {
            this._Presenter.UpdateViewSelection(entity);
        }
        #endregion

        #region visual
        private void mnuVerticeVisual_Click(object sender, RoutedEventArgs e)
        {
            if(!string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                PopupWindow dialog = new PopupWindow();
                dialog.WindowStyle = WindowStyle.None;
                VerticeVisualSetting visualSetting = new VerticeVisualSetting(this.networkGraph.NetworkName);
                visualSetting.NetworkVisualUpdated +=new VerticeVisualSetting.OnNetworkVisualUpdated(HandlesNetworkVisualUpdated);
                dialog.Content = visualSetting;
                dialog.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                dialog.ShowDialog();
            }
        }

	    private void HandlesNetworkVisualUpdated(NetworkVisual netVisual)
	    {
            if (!string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                this.networkGraph.Graph.NetVisual = netVisual;
                this.networkGraph.StartSimulation();
            }
	    }

	    private void mnuEdgeVisual_Click(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                PopupWindow dialog = new PopupWindow();
                dialog.WindowStyle = WindowStyle.None;
                EdgeVisualSetting visualSetting = new EdgeVisualSetting(this.networkGraph.NetworkName);
                visualSetting.NetworkVisualUpdated +=new VerticeVisualSetting.OnNetworkVisualUpdated(HandlesNetworkVisualUpdated);
                dialog.Content = visualSetting;
                dialog.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                dialog.ShowDialog();
            }
        }
        #endregion

        #region filter
        private void mnuExclude_Click(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                NetworkEntityExcludeSetting exSetting = new NetworkEntityExcludeSetting(this.networkGraph.NetworkName);
                exSetting.NetworkExclustionSettingUpdated += new NetworkEntityExcludeSetting.OnNetworkExclustionSettingUpdated(exSetting_NetworkExclustionSettingUpdated);
                PopupWindow dialog=new PopupWindow();
                dialog.Content = exSetting;
                dialog.Show();
            }
        }

        void exSetting_NetworkExclustionSettingUpdated(DiscoveryLogic.Analytics.DataObjects.Filters.NetworkExclusionSetting exSetting)
        {
            this.networkGraph.Graph.ExSetting = exSetting;
            this.networkGraph.StartSimulation();
            //Network network = Network.Read(this.networkGraph.NetworkName);
            //network.ShowAllHiddenVertices();
            //if(exSetting.ExcludeEntityTypes.Count>0)
            //{
            //    foreach(EntityType entityType in exSetting.ExcludeEntityTypes)
            //    {
            //        network.HideVertices(entityType);
            //        network.Save();
            //    }
            //}

            //this.OnViewNetwork(network);
        }

        private void mnuInclude_Click(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                NetworkEntitySelectSetting inSetting = new NetworkEntitySelectSetting(this.networkGraph.NetworkName);
                inSetting.NetworkInclustionSettingUpdated += new NetworkEntitySelectSetting.OnNetworkInclustionSettingUpdated(inSetting_NetworkInclustionSettingUpdated);
                PopupWindow dialog = new PopupWindow();
                dialog.Content = inSetting;
                dialog.Show();
            }
        }

        void inSetting_NetworkInclustionSettingUpdated(DiscoveryLogic.Analytics.DataObjects.Filters.NetworkInclusionSetting inSetting)
        {
            this.networkGraph.Graph.InSetting = inSetting;
            this.networkGraph.StartSimulation();
        }
        #endregion

        #region redraw
        private void mnuRedraw_Click(object sender, RoutedEventArgs e)
        {
            if(!string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                Network network = Network.Read(this.networkGraph.NetworkName);
                this.OnViewNetwork(network);
                //NetworkVisual netVisual = NetworkVisual.Read(this.networkGraph.NetworkName);
                //this.networkGraph.NetVisual = netVisual;
                //NetworkExclusionSetting exSetting = NetworkExclusionSetting.Read(this.networkGraph.NetworkName);
                //this.networkGraph.ExSetting = exSetting;
                //NetworkInclusionSetting inSetting = NetworkInclusionSetting.Read(this.networkGraph.NetworkName);
                //this.networkGraph.InSetting = inSetting;
                //this.networkGraph.StartSimulation();
            }
        }
        #endregion

        #region explore
        private void cmu_ExplorePublications_Click(object sender, RoutedEventArgs e)
	    {
            EntityType tgtEntityType = EntityType.Publications;
            this.ExplorRelations(tgtEntityType);
	    }

	    private void cmu_ExploreOrganizations_Click(object sender, RoutedEventArgs e)
	    {
            EntityType tgtEntityType = EntityType.Organizations;
            this.ExplorRelations(tgtEntityType);
	    }

	    private void cmu_ExplorePersons_Click(object sender, RoutedEventArgs e)
	    {
            EntityType tgtEntityType = EntityType.Persons;
            this.ExplorRelations(tgtEntityType);
	    }

	    private void cmu_ExploreGrants_Click(object sender, RoutedEventArgs e)
	    {
            EntityType tgtEntityType = EntityType.Grants;
            this.ExplorRelations(tgtEntityType);
        }

        private void ExplorRelations(
            EntityType tgtEntityType)
        {
            if(!string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                Network network = Network.Read(this.networkGraph.NetworkName);
                ExploreNetworkAssociation explorer=
                    new ExploreNetworkAssociation(network, RuleType.Link, tgtEntityType);
                explorer.NetworkUpdated += new ExploreNetworkAssociation.OnNetworkUpdated(OnViewNetwork);
                PopupWindow dialog=new PopupWindow();
                dialog.Content = explorer;
                dialog.Show();
            }
        }
        #endregion 

        #region dedup
        private void mnuDedup_Click(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                NetworkDedupEditor netDedupEditor = new NetworkDedupEditor(this.networkGraph.NetworkName);
                netDedupEditor.NetworkDedupSettingUpdated += new NetworkDedupEditor.OnNetworkDedupSettingUpdated(netDedupEditor_NetworkDedupSettingUpdated);
                PopupWindow dialog = new PopupWindow();
                dialog.Content = netDedupEditor;
                dialog.Show();
            }
        }

        void netDedupEditor_NetworkDedupSettingUpdated(
            NetworkDedupSetting networkDedupSetting)
        {
            if (!string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                NetworkDedupWorker dedupWorker=new NetworkDedupWorker(
                    this.networkGraph.NetworkName);
                Network network = dedupWorker.DedupNetwork();
                network.Save();
                this.OnViewNetwork(network);
            }
        }

        #endregion

        #region cluster
        private void cmu_Cluster_Click(object sender, RoutedEventArgs e)
	    {
            if (!string.IsNullOrEmpty(this.networkGraph.NetworkName))
            {
                ClusterNetworkEditor clusterEditor = new ClusterNetworkEditor(this.networkGraph.NetworkName);
                PopupWindow dialog = new PopupWindow();
                dialog.Content = clusterEditor;
                dialog.SizeToContent = SizeToContent.WidthAndHeight;
                clusterEditor.NetworkClustered += new ClusterNetworkEditor.OnNetworkClustered(clusterEditor_NetworkClustered);
                clusterEditor.StatusChanged += new ClusterNetworkEditor.OnStatusChanged(clusterEditor_StatusChanged);
                dialog.Show();
            }
	    }

        void clusterEditor_StatusChanged(string msg, int pct)
        {
            if (this.StatusChanged != null)
                this.StatusChanged(msg, pct);
        }

        void clusterEditor_NetworkClustered(Network network)
        {
            network.Save();
            this.OnViewNetwork(network);
        }
        #endregion

	    #region Implementation of IDisposable

	    /// <summary>
	    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
	    /// </summary>
	    /// <filterpriority>2</filterpriority>
	    public void Dispose()
	    {
	        this.networkGraph.StopSimulation();
	        this.networkGraph.Graph = null;
	    }

	    #endregion
    }
}
